import { _decorator, AudioClip, AudioSource, Color, color, Component, EventTouch, find, instantiate, Label, Node, Prefab, Sprite, UITransform, Vec2, Vec3 } from 'cc';
const { ccclass, property } = _decorator;
import { Blueprint } from './Blueprint';

@ccclass('ColorBoard')
export class ColorBoard extends Component {

    @property({type: Node})
    colorContentNode: Node = null!

    @property({type: Node})
    colorNumberNode: Node = null!

    @property({type: Prefab})
    colorItemPrefab: Prefab = null!

    @property({type: AudioClip})
    selectAudio: AudioClip = null!

    colorData: object = {}
    selectedColor: string = ''
    audioSource: AudioSource = null!

    start() {
        this.initComponents()
        this.initTouchEvents()
    }

    onEnable() {
        this.getColorDataFromLocalStorage()
    }
    
    /** 
     * @zh
     * 从缓存中获取颜色数量。
    */
    getColorDataFromLocalStorage() {
        if (localStorage.getItem('lp-color-data')) {
            this.colorData = JSON.parse(localStorage.getItem('lp-color-data'))
            this.colorContentNode.removeAllChildren()
            for(let colorHex in this.colorData) {
                if (this.colorData[colorHex] <= 0) {
                    continue
                }
                let colorItem = this.spawnColorItem(colorHex)
                this.colorContentNode.addChild(colorItem)
            }
        }
    }

    /** 
     * @zh
     * 更新颜色数量缓存，同时更新界面颜色状态。
    */
    updateColorData(colorHex: string, num: number) {
        // 键如果存在，则只需要关注是否有颜色用完
        if (colorHex in this.colorData) {
            this.colorData[colorHex] += num
        }
        else {
            this.colorData[colorHex] = num
            let colorItem = this.spawnColorItem(colorHex)
            this.colorContentNode.addChild(colorItem)
        }

        // 更新界面文本
        // 只有当前选中颜色和回收时的颜色相同时才更新界面文本数量
        // 之后的代码可能会删除某个键，所以需要在他删除前更新界面文本数量，否则this.colorData[colorHex]会报错
        if (this.selectedColor == colorHex) {
            this.colorNumberNode.getComponent(Label).string = '数量: ' + this.colorData[colorHex].toString()
        }

        // 更新本地缓存
        localStorage.setItem('lp-color-data', JSON.stringify(this.colorData))

        // 如果颜色数量为0，则设置当前选择颜色为空并删除颜色块
        if (this.colorData[colorHex] <= 0) {
            this.colorNumberNode.active = false
            delete this.colorData[colorHex]
            this.selectedColor = ''
            
            for (let i=0; i<this.colorContentNode.children.length; i++) {
                let colorItem = this.colorContentNode.children[i]
                if (colorItem.getComponent(Sprite).color.toHEX() == colorHex) {
                    colorItem.removeFromParent()
                    break
                }
            }
        }
    }

    /** 
     * @zh
     * 初始化组件。
    */
    initComponents() {
        this.audioSource = find('Canvas').getComponent(AudioSource)
    }

    /** 
     * @zh
     * 初始化触摸事件。
    */
    initTouchEvents() {
        this.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this)
    }

    /** 
     * @zh
     * 触摸结束时执行的逻辑。
    */
    onTouchEnd(event: EventTouch) {
        let loc = event.getUILocation()
        let pos = this.colorContentNode.getComponent(UITransform).convertToNodeSpaceAR(new Vec3(loc.x, loc.y, 0))

        // 选中一个颜料
        for (let i=0; i<this.colorContentNode.children.length; i++) {
            let colorItem = this.colorContentNode.children[i]
            if (colorItem.getComponent(UITransform).getBoundingBox().contains(new Vec2(pos.x, pos.y))) {
                this.selectOneColorItem(colorItem)
                break
            }
        }
    }

    /** 
     * @zh
     * 选中一个颜料。
    */
    selectOneColorItem(colorItem: Node) {
        // 添加到撤销操作中
        find('Canvas/Blueprint Background/Blueprint').getComponent(Blueprint).addToUndoStack()
        find('Canvas/Blueprint Background/Blueprint').getComponent(Blueprint).clearRedoStack()

        // 将所有颜色选项恢复原状
        this.resetAllColorItemScale()

        // 将选中的颜色选项变大
        colorItem.setScale(1.2, 1.2, 1)
        
        // 设置选中的颜色
        this.selectedColor = colorItem.getComponent(Sprite).color.toHEX()

        // 显示颜料数量
        this.colorNumberNode.active = true
        this.colorNumberNode.getComponent(Label).string = '数量: ' + this.colorData[this.selectedColor].toString()

        // 播放音频
        this.audioSource.playOneShot(this.selectAudio)
    }

    /** 
     * @zh
     * 恢复所有颜料节点大小。
    */
    resetAllColorItemScale() {
        for (let i=0; i<this.colorContentNode.children.length; i++) {
            let colorItem = this.colorContentNode.children[i]
            colorItem.setScale(1, 1, 1)
        }
    }

    /** 
     * @zh
     * 生成颜料节点。
    */
    spawnColorItem(colorHex: string) {
        let colorItem = instantiate(this.colorItemPrefab)
        colorItem.getComponent(Sprite).color = new Color().fromHEX(colorHex)
        return colorItem
    }

    /** 
     * @zh
     * 通过工具名称选择工具，用于撤销重做功能。
    */
    selectColorItemByName(name: string) {
        if (!name) {
            // 将所有颜色选项恢复原状
            this.resetAllColorItemScale()
            this.selectedColor = ''
            this.colorNumberNode.active = false
            return
        }

        for (let i=0; i<this.colorContentNode.children.length; i++) {
            let colorItem = this.colorContentNode.children[i]

            // 将所有颜色选项恢复原状
            this.resetAllColorItemScale()

            // 将选中的颜色选项变大
            colorItem.setScale(1.2, 1.2, 1)
            
            // 设置选中的颜色
            this.selectedColor = colorItem.getComponent(Sprite).color.toHEX()

            // 显示颜料数量
            this.colorNumberNode.active = true
            this.colorNumberNode.getComponent(Label).string = '数量: ' + this.colorData[this.selectedColor].toString()
            break
        }
    }
}


